/**
 * @author yanggjun
 */
World = {
	ds : 1500,
	floorWidth : 1700,
	floorHeight : 3000,
	modelList : [],
	triggerList : [],
	camera : '',
	targetIndicator : '',
	scene : '',
	container : '',
	renderer : '',
	controls : '',
	stats : '',
	spotLight : '',
	splotLightds : '',
	sky : '',
	map : '',
	floor : '',
	sky : '',
	particleSystem : '',
	wallHeight : 2000,
	

	init : function() {
		this.map = new Map01();
		document.body.style.cursor = 'none';
		if (!Detector.webgl)
			Detector.addGetWebGLMessage();
		this.scene = new THREE.Scene();

		// set the view size in pixels (custom or according to window size)
		var SCREEN_WIDTH = window.innerWidth - 30, SCREEN_HEIGHT = window.innerHeight - 20;
		// camera attributes
		var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 5000000;
		// set up camera
		this.camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
		// add the camera to the scene
		this.scene.add(this.camera);
		// the camera defaults to position (0,0,0)
		//  so pull it back (z = 400) and up (y = 100) and set the angle towards the scene origin
		this.camera.position.set(PlayMan.pos.x, PlayMan.pos.y, PlayMan.pos.z);
		// camera.lookAt(scene.position);
		this.camera.lookAt(new THREE.Vector3(0, 400, -1000000));

		// create and start the renderer; choose antialias setting.
		this.renderer = new THREE.WebGLRenderer({
			antialias : true
		});
		this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
		this.renderer.shadowMapEnabled = true;
		this.renderer.shadowMapSoft = true;
		// create a div element to contain the renderer
		container = document.createElement('div');
		document.body.appendChild(container);

		// attach renderer to the container div
		container.appendChild(this.renderer.domElement);

		// automatically resize renderer
		THREEx.WindowResize(this.renderer, this.camera);
		// toggle full-screen on given key press
		THREEx.FullScreen.bindKey({
			charCode : 'm'.charCodeAt(0)
		});

		// displays current and past frames per second attained by scene
		stats = new Stats();
		stats.domElement.style.position = 'absolute';
		stats.domElement.style.bottom = '0px';
		stats.domElement.style.zIndex = 100;
		container.appendChild(stats.domElement);

		// create a light
		//			var light = new THREE.PointLight(0xff0000);
		//			light.position.set(0, 250, 0);
		//			light.castShadow = true;
		//			this.scene.add(light);
		var ambientLight = new THREE.AmbientLight(0x555555);
		this.scene.add(ambientLight);

		// add directional light source
		var directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
		directionalLight.position.set(1, 1, 1).normalize();
		//this.scene.add(directionalLight);

		//point light
		this.spotLight = new THREE.SpotLight();
		this.spotLight.position.set(0, 1000000, 1000000);
		this.spotLightds = Math.sqrt(2) * 1000000;
		this.spotLight.castShadow = true;
		//			this.spotLight.shadowMapWidth = 3*this.floorWidth; 
		//			this.spotLight.shadowMapHeight = 3*this.floorHeight; 
		//			this.spotLight.shadowCameraNear = 500; 
		this.spotLight.shadowCameraFar = 15000;
		//			this.spotLight.shadowCameraFov = 30;
		this.scene.add(this.spotLight);

		this.initFloor();
		this.initSky();
		//			World.initBuilding();
		this.initObstacle();
		this.initRoomWall();
		MouseEventListener.add();
		KeyEventListener.add();
		TargetIndicator.add();
		Enemy.add();
		this.initParticle();
		Explosion.initParticle();
		World.animate();
		Character.load();
	},

	animate : function() {
		requestAnimationFrame(World.animate);
		EnemyController.positionUpdate();
		PlayMan.positionYUpdate();
		// animateIndicator();
		// animateBuilding();
		Physical.RaiseUpDown(0);
		World.updateParticle();
		Explosion.explode();
		World.render();
		KeyEventListener.handleKeyEvent();
		if(Character.bladeReady == true){
			Character.rotate();
			Character.move();
		}
	},

	render : function() {
		this.renderer.render(this.scene, this.camera);
	},

	initSky : function() {

//		var cubeMaterialArray = [];
//		for ( var j = 0; j < 4; j++) {
//			if (j == 2) {
//				var faceTexture = new THREE.ImageUtils.loadTexture("image/top.jpg");
//				cubeMaterialArray.push(new THREE.MeshBasicMaterial({
//					map : faceTexture
//				}));
//
//			} else {
//				cubeMaterialArray.push(new THREE.MeshBasicMaterial({
//			    	color : 0x9999ff
//				}));
//			}
//		}
//		var skyBoxGeometry = new THREE.CubeGeometry(this.map.sky.length,
//				this.map.sky.width, this.map.sky.height, 1, 1, 1,
//				cubeMaterialArray);
			var skyBoxGeometry = new THREE.CubeGeometry(this.map.sky.length, 150000, this.map.sky.height);
			var faceTexture = new THREE.ImageUtils.loadTexture("image/sky.jpg");
			var skyBoxMaterial = new THREE.MeshBasicMaterial({
//			color : 0x9999ff
			map: faceTexture
		});
//		var skyBox = new THREE.Mesh(skyBoxGeometry,
//				new THREE.MeshFaceMaterial());
		var skyBox = new THREE.Mesh(skyBoxGeometry, skyBoxMaterial);
			skyBox.flipSided = true;
		// render faces from inside of the cube, instead of from outside (default).
		this.scene.add(skyBox);
	},

	initFloor : function() {
		var floorTexture = new THREE.ImageUtils.loadTexture(
				"./image/floor_01.jpg");
		floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
		var floorMaterial = new THREE.MeshBasicMaterial({
			map : floorTexture
		//				color:"0x7b7b7b "
		});
		var floorGeometry = new THREE.PlaneGeometry(this.map.floor.width,
				this.map.floor.length, 1, 1);
		var floor = new THREE.Mesh(floorGeometry, floorMaterial);

		floor.position.set(0, 0, 0);
		floor.receiveShadow = true;
		floor.doubleSided = true;
		this.scene.add(floor);
		this.floorWidth = this.map.floor.width;
		this.floorHeight = this.map.floor.length;
	},

	initRoomWall : function() {

		var wallTexture = new THREE.ImageUtils.loadTexture("./image/014.jpg");
		wallTexture.wrapS = wallTexture.wrapT = THREE.RepeatWrapping;
		wallTexture.repeat.set(10, 5);
		var wallMaterial = new THREE.MeshBasicMaterial({
			map : wallTexture
		//					color:"0xB1B1B1"
		});
		wallMaterial.transparent = true;
		wallMaterial.opacity = 1;
		var wallGeometry = new THREE.PlaneGeometry(this.map.floor.length,
				this.wallHeight, 100, 100);
		var wallB = new THREE.Mesh(wallGeometry, wallMaterial);
		wallB.doubleSided = true;
		wallB.position.set(0, this.wallHeight / 2, -this.map.floor.width / 2);
		wallB.rotation.x = Math.PI / 2
		this.scene.add(wallB);

		wallGeometry = new THREE.PlaneGeometry(this.map.floor.length,
				this.wallHeight, 100, 100);
		var wallF = new THREE.Mesh(wallGeometry, wallMaterial);
		wallF.doubleSided = true;
		wallF.position.set(0, this.wallHeight / 2, this.map.floor.width / 2);
		wallF.rotation.x = Math.PI / 2;
		this.scene.add(wallF);

		wallGeometry = new THREE.PlaneGeometry(this.map.floor.width,
				this.wallHeight, 100, 100);
		var wallL = new THREE.Mesh(wallGeometry, wallMaterial);
		wallL.doubleSided = true;
		wallL.position.set(-this.map.floor.length / 2, this.wallHeight / 2, 0);
		wallL.rotation.z = Math.PI / 2;
		wallL.rotation.x = Math.PI / 2;
		this.scene.add(wallL);

		wallGeometry = new THREE.PlaneGeometry(this.map.floor.width,
				this.wallHeight, 100, 100);
		var wallR = new THREE.Mesh(wallGeometry, wallMaterial);
		wallR.doubleSided = true;
		wallR.position.set(this.map.floor.length / 2, this.wallHeight / 2, 0);
		wallR.rotation.z = Math.PI / 2;
		wallR.rotation.x = Math.PI / 2;
		this.scene.add(wallR);

	},

	initBuilding : function() {
		var buildingList = Model.getModel().building;
		var k = 0;
		var i = 0;
		for (i; i < buildingList.length; i++) {
			var building = buildingList[i];
			var cubeMaterialArray = [];
			var component = building.Component
			var buildingItem = {};
			buildingItem.index = i;
			var itemComponent = [];
			for ( var j = 0; j < component.length; j++) {
				var node = component[j];
				for ( var k = 0; k < node.Color.length; k++) {
					var faceTexture;
					if (k == 2) {
						faceTexture = new THREE.ImageUtils.loadTexture(
								"image/top.jpg");
					} else {
						faceTexture = new THREE.ImageUtils.loadTexture(
								node.Color[k].texture);
					}
					cubeMaterialArray.push(new THREE.MeshBasicMaterial({
						// color : node.Color[k].value
						map : faceTexture

					}));
				}
				var cubeGeometry = new THREE.CubeGeometry(node.Width,
						node.Height, node.Length, 1, 1, 1, cubeMaterialArray);
				var newCube = new THREE.Mesh(cubeGeometry,
						new THREE.MeshFaceMaterial());
				var item = {};
				item.startAnimation = 0;
				item.dy = 0;
				item.direction = -1;
				item.object = newCube;
				item.posx = node.PosX;
				item.posy = node.Height / 2;
				item.posz = node.PosZ;
				itemComponent.push(item);
				newCube.position.set(node.PosX, node.Height / 2, node.PosZ);
				//					newCube.castShadow = true;
				newCube.receiveShadow = true;
				this.scene.add(newCube);
			}
			buildingItem.component = itemComponent;
			this.modelList.push(buildingItem);
			// alert(modelList[i].index);

		}
	},

	initObstacle : function() {
		var obstacle = this.map.building;
		for ( var i = 0; i < obstacle.length; i++) {
			var ob = obstacle[i];
			if (ob.type == "cube") {

				var cubeMaterialArray = [];
				var textureList = ob.texture;
				var faceTexture;
				for ( var j = 0; j < textureList.length; j++) {
					if (j == 2) {
						faceTexture = new THREE.ImageUtils.loadTexture(
								"image/top.jpg");
					} else {
						faceTexture = new THREE.ImageUtils.loadTexture(
								textureList[j].image);
					}
					cubeMaterialArray.push(new THREE.MeshBasicMaterial({
						// color : node.Color[k].value
						map : faceTexture

					}));
				}
				var cubeGeometry = new THREE.CubeGeometry(ob.length, ob.height,
						ob.width, 1, 1, 1, cubeMaterialArray);
				var newCube = new THREE.Mesh(cubeGeometry,
						new THREE.MeshFaceMaterial());
				newCube.position.set(ob.pos.x, ob.pos.y, ob.pos.z);
				var item = {};
				item.posx = ob.pos.x;
				item.posy = ob.pos.y;
				item.posz = ob.pos.z;
				item.ob = newCube;
				item.buildingIndex = i;
				item.wallList = this.getWall(ob);
				//					console.log(item.wallList.length + "***********" + item.wallList[0].lt.x);
				this.modelList.push(item);
				this.scene.add(item.ob);

				var triggerMaterial = new THREE.MeshLambertMaterial({
					color : TriggerModel[i].color
				});
				//var sphereGeometry = new THREE.SphereGeometry(TriggerModel[i].radius, 30, 30);
				//var trigger = new THREE.Mesh(sphereGeometry, triggerMaterial);

				trigger = new THREE.Mesh(new THREE.CylinderGeometry(40, 1, 150,
						50, 10, false), triggerMaterial);
				trigger.overdraw = true;

				TriggerModel[i].pos.x = ob.pos.x;
				TriggerModel[i].pos.y = ob.pos.y + ob.height * 0.6;
				TriggerModel[i].pos.z = ob.pos.z;
				trigger.position.set(ob.pos.x, TriggerModel[i].pos.y, ob.pos.z)
				this.triggerList.push(trigger);
				this.scene.add(trigger);

			}
		}
	},

	getWall : function(ob) {
		var wallList = [];
		var wall = new Object();
		wall.lt = {};
		wall.rt = {};
		wall.rb = {};
		wall.lb = {};

		//			back
		wall.lt.x = ob.pos.x - ob.length / 2;
		wall.lt.y = ob.height;
		wall.lt.z = ob.pos.z - ob.width / 2;

		wall.rt.x = ob.pos.x + ob.length / 2;
		wall.rt.y = ob.height;
		wall.rt.z = ob.pos.z - ob.width / 2;

		wall.rb.x = ob.pos.x + ob.length / 2;
		wall.rb.y = 0;
		wall.rb.z = ob.pos.z - ob.width / 2;

		wall.lb.x = ob.pos.x - ob.length / 2;
		wall.lb.y = 0;
		wall.lb.z = ob.pos.z - ob.width / 2;

		wall.vector = {
			x : 0,
			y : 0,
			z : -1
		};
		wallList.push(wall);

		//			front
		wall = new Object();
		wall.lt = {};
		wall.rt = {};
		wall.rb = {};
		wall.lb = {};
		wall.lt.x = ob.pos.x - ob.length / 2;
		wall.lt.y = ob.height;
		wall.lt.z = ob.pos.z + ob.width / 2;

		wall.rt.x = ob.pos.x + ob.length / 2;
		wall.rt.y = ob.height;
		wall.rt.z = wall.lt.z;

		wall.rb.x = wall.rt.x;
		wall.rb.y = 0;
		wall.rb.z = wall.rt.z;

		wall.lb.x = wall.lt.x;
		wall.lb.y = 0;
		wall.lb.z = wall.lt.z;

		wall.vector = {
			x : 0,
			y : 0,
			z : 1
		};
		wallList.push(wall);
		//			left
		wall = new Object();
		wall.lt = {};
		wall.rt = {};
		wall.rb = {};
		wall.lb = {};
		wall.lt.x = ob.pos.x - ob.length / 2;
		wall.lt.y = ob.height;
		wall.lt.z = ob.pos.z - ob.width / 2;

		wall.rt.x = wall.lt.x;
		wall.rt.y = ob.height;
		wall.rt.z = ob.pos.z + ob.width / 2;

		wall.rb.x = wall.rt.x;
		wall.rb.y = 0;
		wall.rb.z = wall.rt.z;

		wall.lb.x = wall.lt.x;
		wall.lb.y = 0;
		wall.lb.z = wall.lt.z;

		wall.vector = {
			x : -1,
			y : 0,
			z : 0
		};
		wallList.push(wall);
		//			right
		wall = new Object();
		wall.lt = {};
		wall.rt = {};
		wall.rb = {};
		wall.lb = {};
		wall.lt.x = ob.pos.x + ob.length / 2;
		wall.lt.y = ob.height;
		wall.lt.z = ob.pos.z - ob.width / 2;

		wall.rt.x = wall.lt.x;
		wall.rt.y = ob.height;
		wall.rt.z = ob.pos.z + ob.width / 2;

		wall.rb.x = wall.rt.x;
		wall.rb.y = 0;
		wall.rb.z = wall.rt.z;

		wall.lb.x = wall.lt.x;
		wall.lb.y = 0;
		wall.lb.z = wall.lt.z;

		wall.vector = {
			x : 1,
			y : 0,
			z : 0
		};
		wallList.push(wall);

		return wallList;
	},

	initParticle : function() {
		// create the particle variables
		var particleCount = 2000, particles = new THREE.Geometry(), pMaterial = new THREE.ParticleBasicMaterial(
				{
					color : 0xffffff,
					size : 10
				});

		// now create the individual particles
		for ( var p = 0; p < particleCount; p++) {

			// create a particle with random
			// position values, -250 -> 250
			var pX = Math.random() * 500 + 250, pY = Math.random() * 500 - 250, pZ = Math
					.random() * 500 - 250,
			//   particle = new THREE.Vertex(
			particle = new THREE.Vector3(pX, pY, pZ)
			// );

			// add it to the geometry
			particles.vertices.push(particle);
		}

		// create the particle system
		World.particleSystem = new THREE.ParticleSystem(particles, pMaterial);

		// add it to the scene
		this.scene.add(this.particleSystem);
	},

	updateParticle : function() {
		this.particleSystem.rotation.y += 0.01;
	},
}
